home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#42 (Mar 89)
/
Window Source
/
Window2.p
< prev
Wrap
Text File
|
1989-04-04
|
46KB
|
1,736 lines
(*
© 1988, Apple Computer, Inc.
All rights reserved.
Window2.p: A HyperCard XCMD in MPW Pascal 2.0.2 by Joe Zuffoletto
Version 1.0, 29 June 1988
Form: window title,top,left,bottom,right
Example: window "My Window",50,100,300,400
Notes: Window puts up a standard document window with scroll bars.
The window can be dragged, resized, zoomed, and closed.
Command-W is supported for closing the window. Command-spacebar
toggles the menubar on and off, as in HyperCard. If you
try to draw the window's title bar off the screen or under
the menubar, Window will abort with an error message. Error
messages can be examined by looking at HyperCard's global
variable "the result" after calling Window.
Window is MultiFinder friendly and works with all
versions of HyperCard through 1.2.1. It supports multiple
displays on the Mac II as well.
Window takes a snapshot of the HyperCard card window and
displays it like a MacPaint document. You can scroll up
and down, etc. This is just for demonstration and amusement.
You must supply your own code for displaying whatever you
want to display in the window.
-----------------------------------------------------------------------------
To compile and link this file using MPW Pascal 2.0.2, select the following lines
and press ENTER:
Pascal Window2.p
link -o "Hard Disk":HyperCard:"HyperCard Stacks":Home ∂
-rt XCMD=2000 -sn Main=Window ∂
Window2.p.o {MPW}Libraries:Interface.o ∂
{MPW}PLibraries:PasLib.o ∂
-m ENTRYPOINT
Use other link files as necessary.
The above link directives install the XCMD resource into the Home stack. You
can substitute the name of any stack you want; be sure to provide the
correct pathname. Also, make sure the target stack already has a resource
fork or it won't work. You can create an empty resource fork in a stack
with ResEdit.
-----------------------------------------------------------------------------
*)
{$R-}
{$S Window}
UNIT DummyUnit;
INTERFACE
USES MemTypes,QuickDraw,OSIntf,ToolIntf,PasLibIntf,HyperXCmd;
PROCEDURE EntryPoint(paramPtr:XCmdPtr);
IMPLEMENTATION
TYPE Str31 = String[31];
OffScrHandle = ^OffScrRecPtr; {Attach to refCon of a window}
OffScrRecPtr = ^OffScrRecord;
OffScrRecord = RECORD
gPort: GrafPtr; {Offscreen GrafPort}
docWidth: INTEGER; {Document's width in pixels}
docHeight: INTEGER; {Document's height in pixels}
blitRect: Rect; {'Window' onto O.G.}
blitWidth: INTEGER; {Current width of O.G. 'window'}
blitHeight: INTEGER; {Current height of O.G. 'window'}
dhGraf: LONGINT; {Pixels scrolled horizontally}
dvGraf: LONGINT; {Pixels scrolled vertically}
END;
ScrollHandle = ^ScrollPtr; {Attach to refCon of a scroll bar}
ScrollPtr = ^ScrollRecord;
ScrollRecord = RECORD
heldDown: INTEGER; {See procedure MyScroll}
goFast: BOOLEAN;
END;
PROCEDURE Window(paramPtr:XCmdPtr);FORWARD;
PROCEDURE EntryPoint(paramPtr:XCmdPtr);
BEGIN
Window(paramPtr);
END;
FUNCTION Min(int1,int2:INTEGER): INTEGER;
{Return the smaller of two integers.}
BEGIN
IF (int1 <= int2) THEN
Min := int1
ELSE
Min := Int2;
END; {Min}
PROCEDURE InitBlit(theWindow:WindowPtr);
{Initialize the blit rectangle so it is in the upper left
corner of the offscreen bitmap and so it is the same size
as the target window onscreen.}
VAR
myOffScrHandle: OffScrHandle;
BEGIN
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
WITH myOffScrHandle^^ DO
BEGIN
dhGraf := 0;
dvGraf := 0;
{Make sure blit rectangle doesn't hang off edges of offscreen bitmap, just
in case window is larger.}
blitWidth := Min((theWindow^.portRect.right - 15 - theWindow^.portRect.left),docWidth);
blitHeight := Min((theWindow^.portRect.bottom - 15 - theWindow^.portRect.top),docHeight);
SetRect(blitRect,gPort^.portBits.bounds.left,
gPort^.portBits.bounds.top,
gPort^.portBits.bounds.left + blitWidth,
gPort^.portBits.bounds.top + blitHeight);
END;
HUnlock(Handle(myOffScrHandle));
END; {InitBlit}
PROCEDURE InvalContents(theWindow:WindowPtr;theOldSize:Rect);
{Perform "intelligent" window updating; i.e., if the window is
grown, invalidate for the update event only the part that wasn't
visible before.}
VAR
myOffScrHandle: OffScrHandle;
myWindowRect,windowRect: Rect;
tallRect,wideRect: Rect;
hWhiteSpace,vWhiteSpace: INTEGER;
hBlitOffset,vBlitOffset: INTEGER;
myDocWidth,myDocHeight: INTEGER;
newDhGraf,newDvGraf: LONGINT;
tempDH,tempDV: LONGINT;
BEGIN
hBlitOffset := 0;
vBlitOffset := 0;
myWindowRect := theWindow^.portRect;
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
WITH myOffScrHandle^^ DO
BEGIN
tempDH := dhGraf;
tempDV := dvGraf;
myDocWidth := docWidth;
myDocHeight := docHeight;
END;
{If we have scrolled to the bottom and/or right edges of the document and then
grow the window, the document will "follow" the window so we don't just expose
a lot of white space. The same thing will happen if we zoom the window to a
larger size. In either case, we need to invalidate the entire content region.}
{Is any white space being exposed in the horizontal direction?}
hWhiteSpace := (myWindowRect.right - myWindowRect.left - 15) - (myDocWidth - tempDH);
IF (hWhiteSpace > 0) THEN
BEGIN
{If so, how much?}
newDhGraf := tempDH - hWhiteSpace;
{Move the document that distance, but not beyond the point where its
left edge is flush with the left edge of the window.}
IF newDhGraf < 0 THEN
newDhGraf := 0;
{Adjust blit rectangle accordingly.}
hBlitOffset := INTEGER(tempDH - newDhGraf);
tempDH := newDhGraf;
END; {IF hWhiteSpace}
{Repeat for vertical direction.}
vWhiteSpace := (myWindowRect.bottom - myWindowRect.top - 15) - (myDocHeight - tempDV);
IF (vWhiteSpace > 0) THEN
BEGIN
newDvGraf := tempDV - vWhiteSpace;
IF newDvGraf < 0 THEN
newDvGraf := 0;
vBlitOffset := INTEGER(tempDV - newDvGraf);
tempDV := newDvGraf;
END; {IF vWhiteSpace}
{Save what we've learned to the data structure.}
WITH myOffScrHandle^^ DO
BEGIN
dhGraf := tempDH;
dvGraf := tempDV;
blitWidth := Min((myWindowRect.right - myWindowRect.left - 15),
(myDocWidth - dhGraf));
blitHeight := Min((myWindowRect.bottom - myWindowRect.top - 15),
(myDocHeight - dvGraf));
SetRect(blitRect,blitRect.left - hBlitOffset,
blitRect.top - vBlitOffset,
blitRect.left + blitWidth - hBlitOffset,
blitRect.top + blitHeight - vBlitOffset);
blitWidth := blitRect.right - blitRect.left;
blitHeight := blitRect.bottom - blitRect.top;
END;
HUnlock(Handle(myOffScrHandle));
{If the document has followed the window, invalidate entire content
region.}
IF ((hBlitOffset <> 0) OR (vBlitOffset <> 0)) THEN
BEGIN
EraseRect(theWindow^.portRect);
InvalRect(theWindow^.portRect);
END
ELSE
{Otherwise invalidate only the new white space.}
BEGIN
SetRect(tallRect,theOldSize.right,
theWindow^.portRect.top,
theWindow^.portRect.right,
theWindow^.portRect.bottom);
SetRect(wideRect,theWindow^.portRect.left,
theOldSize.bottom,
theOldSize.right,
theWindow^.portRect.bottom);
EraseRect(tallRect);
EraseRect(wideRect);
InvalRect(tallRect);
InvalRect(wideRect);
END; {IF hBlitOffset}
END; {InvalContents}
PROCEDURE DrawContents(theWindow:WindowPtr);
{Blasts contents of updated blit rectangle to screen.}
VAR
myWindowRect,windowRect: Rect;
myOffScrHandle: OffScrHandle;
BEGIN
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
myWindowRect := theWindow^.portRect;
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
SetRect(windowRect,myWindowRect.left,
myWindowRect.top,
myWindowRect.left + myOffScrHandle^^.blitWidth,
myWindowRect.top + myOffScrHandle^^.blitHeight);
ClipRect(windowRect);
CopyBits(myOffScrHandle^^.gPort^.portBits,theWindow^.portBits,
myOffScrHandle^^.blitRect,windowRect,
srcCopy,NIL);
HUnlock(Handle(myOffScrHandle));
END; {DrawContents}
PROCEDURE ScrollContents(theWindow:WindowPtr;dh,dv:INTEGER);
VAR
myOffScrHandle: OffScrHandle;
leftSpace,topSpace: INTEGER;
rightSpace,bottomSpace: INTEGER;
BEGIN
{ Calculate space between edges of blitRect and edges of the bitmap. }
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
WITH myOffScrHandle^^ DO
BEGIN
leftSpace := gPort^.portBits.bounds.left - blitRect.left;
topSpace := gPort^.portBits.bounds.top - blitRect.top;
rightSpace := gPort^.portBits.bounds.right - blitRect.right;
bottomSpace := gPort^.portBits.bounds.bottom - blitRect.bottom;
END;
{ Then move blitRect, but not past the edge of the bitmap. }
IF (dv = 0) THEN
IF (dh > 0) THEN {moving to the right}
IF (rightSpace > dh) THEN
OffsetRect(myOffScrHandle^^.blitRect,dh,dv)
ELSE
BEGIN
dh := rightSpace;
OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
END
ELSE {moving to the left}
IF (leftSpace > dh) THEN
BEGIN
dh := leftSpace;
OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
END
ELSE
OffsetRect(myOffScrHandle^^.blitRect,dh,dv)
ELSE IF (dv > 0) THEN {moving down}
IF (bottomSpace > dv) THEN
OffsetRect(myOffScrHandle^^.blitRect,dh,dv)
ELSE
BEGIN
dv := bottomSpace;
OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
END
ELSE IF (topSpace > dv) THEN {moving up}
BEGIN
dv := topSpace;
OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
END
ELSE
OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
{Save actual distances moved to data structure.}
WITH myOffScrHandle^^ DO
BEGIN
dhGraf := dhGraf + dh;
dvGraf := dvGraf + dv;
END;
HUnlock(Handle(myOffScrHandle));
{Shoot new contents of blit rectangle to screen.}
DrawContents(theWindow);
END; {ScrollContents}
PROCEDURE MyScroll(theControl:ControlHandle;partCode:INTEGER);
VAR
myOffScrHandle: OffScrHandle;
myScrollHandle: ScrollHandle;
dh,dv: LONGINT;
windowFull: LONGINT;
myCtlValue: LONGINT;
visHeight,visWidth: LONGINT;
dontCare: LONGINT;
tempDH,tempDV: LONGINT;
startValue: INTEGER;
myDocWidth,myDocHeight: INTEGER;
direction: Str255;
theWindow: WindowPtr;
BEGIN
theWindow := theControl^^.contrlOwner;
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
{Make local copies of data structure items.}
WITH myOffScrHandle^^ DO
BEGIN
tempDH := dhGraf;
tempDV := dvGraf;
myDocWidth := docWidth;
myDocHeight := docHeight;
END;
HUnlock(Handle(myOffScrHandle));
{Initialize more variables for our formulas.}
visHeight := theWindow^.portRect.bottom - 15 - theWindow^.portRect.top;
visWidth := theWindow^.portRect.right - 15 - theWindow^.portRect.left;
startValue := GetCtlValue(theControl);
GetCTitle(theControl,direction);
myScrollHandle := ScrollHandle(GetCRefCon(theControl));
MoveHHi(Handle(myScrollHandle));
HLock(Handle(myScrollHandle));
{Implementation of two-speed, accelerating scroll bars.}
WITH myScrollHandle^^ DO
BEGIN
heldDown := heldDown + 1;
IF (heldDown > 2) THEN
goFast := TRUE;
END; {WITH}
CASE partCode OF
inUpButton:
BEGIN
{Don't scroll up if already at top!}
IF (startValue > 0) THEN
BEGIN
IF (direction = 'MyVert') THEN
BEGIN
IF (visHeight >= myDocHeight) THEN
BEGIN
setCtlValue(theControl,0);
ScrollContents(theWindow,0,-tempDV);
END
ELSE
BEGIN
{Scroll up five pixels}
dv := tempDV - 5;
{Set new thumb value using Golden Ratio.}
myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
{Update blit rectangle, blast document to screen.}
ScrollContents(theWindow,0,-5);
END; {IF visHeight...ELSE}
END
ELSE
BEGIN
{Repeat for horizontal direction.}
IF (visWidth >= myDocWidth) THEN
BEGIN
setCtlValue(theControl,0);
ScrollContents(theWindow,-tempDH,0);
END
ELSE
BEGIN
dh := tempDH - 5;
myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,-5,0);
END; {IF visWidth...ELSE}
END; {IF direction...ELSE}
END; {IF startValue}
IF (myScrollHandle^^.goFast = FALSE) THEN
Delay(10,dontCare);
END; {inUpButton}
{Pattern is identical for down button, page up, and page down regions.}
inDownButton:
BEGIN
IF (direction = 'MyVert') THEN
BEGIN
IF (startValue < myDocHeight) THEN
BEGIN
dv := tempDV + 5;
myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,0,5);
END; {IF startValue}
END
ELSE
BEGIN
IF (startValue < myDocWidth) THEN
BEGIN
dh := tempDH + 5;
myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,5,0);
END; {IF startValue}
END; {IF direction... ELSE}
IF (myScrollHandle^^.goFast = FALSE) THEN
Delay(10,dontCare);
END; {inDownButton}
inPageUp:
BEGIN
IF (startValue > 0) THEN
BEGIN
IF (direction = 'MyVert') THEN
BEGIN
IF (visHeight >= myDocHeight) THEN
BEGIN
setCtlValue(theControl,0);
ScrollContents(theWindow,0,-tempDV);
END
ELSE
BEGIN
windowFull := visHeight - 5;
dv := tempDV - windowFull;
IF (dv < 0) THEN
dv := 0;
myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,0,-windowFull);
END; {IF visHeight...ELSE}
END {IF direction}
ELSE
BEGIN
IF (visWidth >= myDocWidth) THEN
BEGIN
setCtlValue(theControl,0);
ScrollContents(theWindow,-tempDH,0);
END
ELSE
BEGIN
windowFull := visWidth - 5;
dh := tempDH - windowFull;
IF (dh < 0) THEN
dh := 0;
myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,-windowFull,0);
END; {IF visWidth...ELSE}
END; {IF direction... ELSE}
IF (myScrollHandle^^.goFast = FALSE) THEN
Delay(10,dontCare);
END; {IF startValue}
END; {inPageUp}
inPageDown:
BEGIN
IF (direction = 'MyVert') THEN
BEGIN
IF (startValue < myDocHeight) THEN
BEGIN
windowFull := visHeight - 5;
dv := tempDV + windowFull;
myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,0,windowFull);
END; {IF startValue}
END {IF direction}
ELSE
BEGIN
IF (startValue < myDocWidth) THEN
BEGIN
windowFull := visWidth - 5;
dh := tempDH + windowFull;
myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
ClipRect(theWindow^.portRect);
setCtlValue(theControl,INTEGER(myCtlValue));
ScrollContents(theWindow,windowFull,0);
END; {IF startValue}
END; {IF direction... ELSE}
IF (myScrollHandle^^.goFast = FALSE) THEN
Delay(10,dontCare);
END; {inPageDown}
END; {CASE partCode}
HUnlock(Handle(myScrollHandle));
ClipRect(theWindow^.portRect); {so TrackControl can unhilite arrows when mouse is released}
END; {MyScroll}
PROCEDURE Window(paramPtr:XCmdPtr);
CONST
minParamCount = 5;
smallestHeight = 100;
smallestWidth = 100;
_WaitNextEvent = $A860;
_Unimplemented = $A89F;
active = 0;
inactive = 255;
MouseMovedEvt = $FA;
SuspendResumeEvt = $01;
SuspendEventMask = $1;
ConvertScrapMask = $2;
browseTool = 6069;
HCWidth = 512;
HCHeight = 342;
padding = 16;
VAR
toolVis,patVis: BOOLEAN;
msgVis,fatVis: BOOLEAN;
hasWaitNextEvent: BOOLEAN;
inBackGround,smallScreen: BOOLEAN;
DoneFlag,HaveEvent: BOOLEAN;
menuWasHidden: BOOLEAN;
wTop,wLeft,wBottom,wRight: INTEGER;
partCode,controlCode: INTEGER;
largestHeight,largestWidth: INTEGER;
dummy,charCode: INTEGER;
screenWidth,screenHeight: INTEGER;
myDocWidth,myDocHeight: INTEGER;
eventPoint: Point;
wRect,screenRect,dragRect: Rect;
winSizeLimits: Rect;
oldSize: Rect;
newSize,dontCare: LONGINT;
envError: OSErr;
cursorRgn: RgnHandle;
hScroll,vScroll: ControlHandle;
whichControl: ControlHandle;
myWindow,whichWindow: WindowPtr;
fatBitsWindow: WindowPtr;
HCrefresh: Str31;
wT,wL,wB,wR,wTitle: Str255;
toolStr,patStr,msgStr: Str255;
widthStr,heightStr: Str255;
myBits: BitMap;
theEnv: SysEnvRec;
myEvent: EventRecord;
wRecord: WindowRecord;
HCPort: GrafPtr;
theOffScrHandle: OffScrHandle;
theScrollHandle: ScrollHandle;
myOffScr: OffScrRecord;
myScrollRecord: ScrollRecord;
FUNCTION TrapAvailable(tNumber: INTEGER; tType: TrapType):BOOLEAN;
{Check to see if a given trap is implemented.}
BEGIN
TrapAvailable := NGetTrapAddress(tNumber, tType) <> GetTrapAddress(_Unimplemented);
END; {TrapAvailable}
FUNCTION CreateHScrollBar(theWindow:WindowPtr;theValue,theMin,theMax:INTEGER;theRefCon:LONGINT):ControlHandle;
VAR
myWindowRect,hScrRect : Rect;
BEGIN
SetPort(theWindow);
myWindowRect := theWindow^.portRect;
SetRect(hScrRect,myWindowRect.left -1,
myWindowRect.bottom - 15,
myWindowRect.right - 14,
myWindowRect.bottom + 1);
CreateHScrollBar := NewControl(theWindow,hScrRect,'MyHoriz',TRUE,
theValue,theMin,theMax,scrollBarProc,theRefCon);
END; {CreateHScrollBar}
FUNCTION CreateVScrollBar(theWindow:WindowPtr;theValue,theMin,theMax:INTEGER;theRefCon:LONGINT):ControlHandle;
VAR
myWindowRect,hScrRect : Rect;
BEGIN
SetPort(theWindow);
myWindowRect := theWindow^.portRect;
SetRect(hScrRect,myWindowRect.right -15,
myWindowRect.top - 1,
myWindowRect.right + 1,
myWindowRect.bottom - 14);
CreateVScrollBar := NewControl(theWindow,hScrRect,'MyVert',TRUE,
theValue,theMin,theMax,scrollBarProc,theRefCon);
END; {CreateVScrollBar}
PROCEDURE InvalScroll(theWindow:WindowPtr);
VAR
theRect,tallRect,wideRect : Rect;
BEGIN
SetPort(theWindow);
theRect := theWindow^.portRect;
ClipRect(theRect);
{ Accumulate tallRect, which is occupied by the vertical scroll bar }
SetRect(tallRect,theRect.right-15,
theRect.top,
theRect.right,
theRect.bottom);
EraseRect(tallRect);
InvalRect(tallRect);
{ Accumulate wideRect, which is occupied by the horizontal scroll bar }
SetRect(wideRect,theRect.left,
theRect.bottom-15,
theRect.right,
theRect.bottom);
EraseRect(wideRect);
InvalRect(wideRect);
END; {InvalScroll}
PROCEDURE Deactivate(theWindow:WindowPtr);
{Deactivate the scroll bars in theWindow in accordance
with the human interface guidelines. This means we must
erase everything enclosed by the control rectangles.}
VAR
theControl: ControlHandle;
theControlRect: Rect;
BEGIN
{I always title my scroll bars 'MyVert' and 'MyHoriz'
so I can easily find them by walking the window's
control list.}
theControl := WindowPeek(theWindow)^.controlList;
WHILE (theControl <> NIL) DO
BEGIN
IF (theControl^^.contrlTitle = 'MyVert') OR
(theControl^^.contrlTitle = 'MyHoriz') THEN
BEGIN
theControlRect := theControl^^.contrlRect;
InsetRect(theControlRect,1,1);
EraseRect(theControlRect);
END; {IF}
theControl := theControl^^.nextControl;
END; {WHILE}
END; {Deactivate}
PROCEDURE HiliteScrollBars(theWindow:WindowPtr);
VAR
myWindowRect: Rect;
visWidth,visHeight: INTEGER;
myDocWidth,myDocHeight: INTEGER;
myCtlValue: INTEGER;
tempDH,tempDV: LONGINT;
myOffScrHandle: OffScrHandle;
BEGIN
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
{Make local copies of data structure items.}
WITH myOffScrHandle^^ DO
BEGIN
tempDH := dhGraf;
tempDV := dvGraf;
myDocWidth := docWidth;
myDocHeight := docHeight;
END;
HUnlock(Handle(myOffScrHandle));
myWindowRect := theWindow^.portRect;
visHeight := myWindowRect.bottom - 15 - myWindowRect.top;
visWidth := myWindowRect.right - 15 - myWindowRect.left;
SetPort(theWindow);
ClipRect(myWindowRect);
{ Check to see if window is taller than contents. If
so, unhilite vertical scroll bar. Otherwise, use
Golden Ratio to draw vertical scroll bar with thumb
in right position. }
IF ((visHeight >= myDocHeight) AND (tempDV = 0)) THEN
HiliteControl(vScroll,INTEGER(inactive))
ELSE
BEGIN
HiliteControl(vScroll,INTEGER(active));
IF (visHeight >= myDocHeight) THEN
SetCtlValue(vScroll,myDocHeight)
ELSE
BEGIN
myCtlValue := LONGINT((tempDV * myDocHeight) DIV (myDocHeight - visHeight));
ClipRect(theWindow^.portRect);
setCtlValue(vScroll,INTEGER(myCtlValue));
END; {IF visHeight...ELSE}
END;
{ Repeat for horizontal scroll bar. }
IF ((visWidth >= myDocWidth) AND (tempDH = 0)) THEN
HiliteControl(hScroll,INTEGER(inactive))
ELSE
BEGIN
HiliteControl(hScroll,INTEGER(active));
IF (visWidth >= myDocWidth) THEN
SetCtlValue(hScroll,myDocWidth)
ELSE
BEGIN
myCtlValue := LONGINT((tempDH * myDocWidth) DIV (myDocWidth - visWidth));
ClipRect(theWindow^.portRect);
setCtlValue(hScroll,INTEGER(myCtlValue));
END; {IF visWidth...ELSE}
END;
END; {HiliteScrollBars}
PROCEDURE MoveScrollBars(theWindow:WindowPtr);
VAR
myWindowRect: Rect;
vScrRect,hScrRect: Rect;
BEGIN
myWindowRect := theWindow^.portRect;
SetRect(hScrRect,myWindowRect.left - 1,
myWindowRect.bottom - 15,
myWindowRect.right - 14,
myWindowRect.bottom + 1);
SetRect(vScrRect,myWindowRect.right - 15,
myWindowRect.top - 1,
myWindowRect.right + 1,
myWindowRect.bottom - 14);
SetPort(theWindow);
ClipRect(myWindowRect);
{ Hide and resize the scroll bars to fit the new window size. }
HideControl(hScroll);
HideControl(vScroll);
MoveControl(hScroll,hScrRect.left,hScrRect.top);
SizeControl(hScroll,(hScrRect.right - hScrRect.left),
(hScrRect.bottom - hScrRect.top));
MoveControl(vScroll,vScrRect.left,vScrRect.top);
SizeControl(vScroll,(vScrRect.right - vScrRect.left),
(vScrRect.bottom - vScrRect.top));
HiliteScrollBars(theWindow);
ShowControl(hScroll);
ShowControl(vScroll);
END; {MoveScrollBars}
PROCEDURE ScrollWithThumb(theControl:ControlHandle;theEventPoint:Point);
VAR
theWindow: WindowPtr;
myOffScrHandle: OffScrHandle;
visWidth,visHeight: INTEGER;
myDocWidth,myDocHeight: INTEGER;
startValue,endValue: INTEGER;
dummy: INTEGER;
amountToScroll: LONGINT;
tempDH,tempDV: LONGINT;
direction: Str255;
BEGIN
theWindow := theControl^^.contrlOwner;
myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
MoveHHi(Handle(myOffScrHandle));
HLock(Handle(myOffScrHandle));
{Make local copies of data structure items.}
WITH myOffScrHandle^^ DO
BEGIN
tempDH := dhGraf;
tempDV := dvGraf;
myDocWidth := docWidth;
myDocHeight := docHeight;
END;
HUnlock(Handle(myOffScrHandle));
GetCTitle(theControl,direction);
visHeight := theWindow^.portRect.bottom -
theWindow^.portRect.top - 15;
visWidth := theWindow^.portRect.right -
theWindow^.portRect.left - 15;
{Record where thumb is before it is moved.}
startValue := GetCtlValue(theControl);
{Move it.}
dummy := TrackControl(theControl,theEventPoint,NIL);
{Record where thumb is released.}
endValue := GetCtlValue(theControl);
{Record the distance thumb was moved.}
amountToScroll := LONGINT(endValue - startValue);
IF (direction = 'MyVert') THEN
BEGIN {moved vertical scroll bar}
IF (endValue = 0) THEN {moved thumb to top}
ScrollContents(theWindow,0,-tempDV)
ELSE
IF (endValue = myDocHeight) THEN {moved thumb to bottom}
ScrollContents(theWindow,0,myDocHeight - tempDV)
ELSE
BEGIN
{moved thumb somewhere in middle - use Golden Ratio to
translate thumb movement into document movement.}
amountToScroll := LONGINT((amountToScroll *
(myDocHeight - visHeight)) DIV
myDocHeight);
IF (ABS(amountToScroll) < 1) THEN
{didn't move thumb far enough to scroll - snap it
back to starting position.}
SetCtlValue(theControl,startValue)
ELSE
ScrollContents(theWindow,0,INTEGER(amountToScroll));
END;
END
ELSE {moved horizontal scroll bar}
BEGIN
IF (endValue = 0) THEN
ScrollContents(theWindow,-tempDH,0)
ELSE
IF (endValue = myDocWidth) THEN
ScrollContents(theWindow,myDocWidth - tempDH,0)
ELSE
BEGIN
amountToScroll := LONGINT((amountToScroll *
(myDocWidth - visWidth)) DIV
myDocWidth);
IF (ABS(amountToScroll) < 1) THEN
SetCtlValue(theControl,startValue)
ELSE
ScrollContents(theWindow,INTEGER(amountToScroll),0);
END;
END;
END; {ScrollWithThumb}
FUNCTION WhichDevice(thePoint:Point):GDHandle;
VAR
aDevice: GDHandle;
foundOne: BOOLEAN;
BEGIN
aDevice := GetDeviceList;
foundOne := FALSE;
WHILE (aDevice <> NIL) AND NOT foundOne DO
BEGIN
IF PtInRect(thePoint,aDevice^^.gdRect) THEN
BEGIN
WhichDevice := aDevice;
foundOne := TRUE;
END;
aDevice := aDevice^^.gdNextGD;
END;
END; { WhichDevice }
FUNCTION MenuBarHeight: INTEGER;
{Returns the height of the menubar in pixels, as
read from the low memory global mBarHeight.}
CONST
mBarHeight = $BAA;
VAR
menuBarHeightPtr: ^INTEGER;
BEGIN
menuBarHeightPtr := Pointer(mBarHeight);
MenuBarHeight := menuBarHeightPtr^;
END; {MenuBarHeight}
FUNCTION OnAScreen(theRect:Rect):BOOLEAN;
CONST
titleBarHeight = 18;
VAR
deskRgn: RgnHandle;
topLeft,topRight: Point;
BEGIN
deskRgn := GetGrayRgn;
topLeft.v := theRect.top - titleBarHeight;
topLeft.h := theRect.left + titleBarHeight;
topRight.v := topLeft.v;
topRight.h := theRect.right - titleBarHeight;
IF ((PtInRgn(topLeft,deskRgn)) OR (PtInRgn(topRight,deskRgn))) THEN
OnAScreen := TRUE
ELSE
OnAScreen := FALSE;
END; {OnAScreen}
PROCEDURE ZoomIt(theWindow:WindowPtr;partCode:INTEGER;clickedWhere:Point);
CONST
titleBarHeight = 18;
TYPE
WStatePtr = ^WStateData;
WStateHandle = ^WStatePtr;
VAR
oldRect,newRect: Rect;
maxHeight: INTEGER;
BEGIN
oldRect := theWindow^.portRect;
IF theEnv.hasColorQD THEN
BEGIN
newRect := WhichDevice(clickedWhere)^^.gdRect;
IF WhichDevice(clickedWhere) = GetMainDevice THEN
BEGIN
newRect.top := newRect.top + MenuBarHeight;
END;
END
ELSE
newRect := GetGrayRgn^^.rgnBBox;
newRect.left := newRect.left + 2;
newRect.top := newRect.top + titleBarHeight + 2;
newRect.right := newRect.right - 3;
newRect.bottom := newRect.bottom - 3;
IF NOT EqualRect(oldRect,newRect) THEN
WITH WindowPeek(theWindow)^ DO
WStateHandle(dataHandle)^^.stdState := newRect;
SetPort(theWindow);
EraseRect(whichWindow^.portRect);
InvalRect(whichWindow^.portRect);
ZoomWindow(theWindow,partcode,FALSE);
END; { ZoomIt }
{$I XCmdGlue.inc}
PROCEDURE Fail(errStr:Str255);
{Fail returns errStr to HyperCard and exits the XCMD.
errStr can then be checked by inspecting HyperCard's
global variable "the result." See "XCMD's for Hyper-
Card" by Gary Bond (MIS Press, 1988) for more details.
© 1988 by Gary Bond
All rights reserved.
You may use this code for NON-COMMERCIAL purposes.}
BEGIN
paramPtr^.returnValue := PasToZero(errStr);
SysBeep(1);
EXIT(Window);
END; {Fail}
PROCEDURE CheckParamCount;
{CheckParamCount sees if the number of parameters
passed to the XCMD matches the number expected. If
not, we exit from the XCMD with an error message.
See "XCMD's for HyperCard" by Gary Bond (MIS Press,
1988) for more details.
© 1988 by Gary Bond
All rights reserved.
You may use this code for NON-COMMERCIAL purposes.}
VAR
numParams : INTEGER;
BEGIN
numParams := paramPtr^.paramCount;
IF(numParams <> minParamCount) THEN
Fail('Form: HyperWindow "Window Title",top,left,bottom,right');
END; {CheckParamCount}
FUNCTION GetHCVersion:Str255;
{Return a string containing the version of HyperCard
being used; e.g., '1.2'}
BEGIN
ZeroToPas(EvalExpr('the version')^,GetHCVersion);
END;
PROCEDURE HideWindoids;
{Get and save the visible state of the tool, pattern,
message and fatbits windoids; then hide them if they
are showing.}
VAR
toolH,patH,msgH,fatH: Handle;
PROCEDURE HideFatBits;
{HyperCard does not have a built-in command for hiding
and showing the fatbits windoid, so we have to do it
ourselves. HideFatBits walks the window list until it
finds a window with title "FatBits," then hides it if
the visible field of its WindowRecord is true.
HideFatBits also saves the WindowPtr to the fatbits
windoid so we can use it later (e.g., to show the
windoid again).}
CONST
windowList = $9D6; {Low memory global location.}
VAR
theWindow: WindowPeek;
theWindowPtr: ^WindowPtr;
BEGIN
theWindowPtr := Pointer(windowList);
theWindow := WindowPeek(theWindowPtr^);
fatVis := FALSE;
WHILE (theWindow <> NIL) DO
BEGIN
IF (theWindow^.titleHandle^^ = 'FatBits') THEN
BEGIN
fatBitsWindow := WindowPtr(theWindow);
IF (theWindow^.visible = TRUE) THEN
BEGIN
fatVis := TRUE;
HideWindow(fatBitsWindow);
theWindow := NIL;
END;
END;
IF (theWindow <> NIL) THEN
theWindow := WindowPeek(theWindow)^.nextWindow;
END; {WHILE}
END; {HideFatBits}
BEGIN {HideWindoids}
{Get visible state of windoids.}
toolH := EvalExpr('visible of tool window');
ZeroToPas(toolH^,toolStr);
DisposHandle(toolH);
toolVis := StrToBool(toolStr);
patH := EvalExpr('visible of pattern window');
ZeroToPas(patH^,patStr);
DisposHandle(patH);
patVis := StrToBool(patStr);
msgH := EvalExpr('visible of message window');
ZeroToPas(msgH^,msgStr);
DisposHandle(msgH);
msgVis := StrToBool(msgStr);
{Hide the ones that are showing.}
HideFatBits;
IF toolVis THEN
SendHCMessage('hide tool window');
IF patVis THEN
SendHCMessage('hide pattern window');
IF msgVis THEN
SendHCMessage('hide message window');
END; {HideWindoids}
PROCEDURE ShowWindoids;
{This routine assumes HideWindoids has been called
before. ShowWindoids restores the visible state of
the windoids to that saved by HideWindoids.}
BEGIN
IF toolVis THEN
SendHCMessage('show tool window');
IF patVis THEN
SendHCMessage('show pattern window');
IF msgVis THEN
SendHCMessage('show message window');
{As in HideWindoids, we must take care of the FatBits
windoid ourselves.}
IF fatVis THEN
BEGIN
ShowWindow(fatBitsWindow);
SelectWindow(fatBitsWindow);
END;
END; {ShowWindoids}
PROCEDURE ToggleMenuBar;
{Set the visible of the menubar to not the visible of
the menubar.}
BEGIN
IF MenuBarHeight = 0 THEN
SendHCMessage('show menuBar')
ELSE
SendHCMessage('hide menuBar');
END; {ToggleMenuBar}
PROCEDURE GetHCBitMap;
VAR
myDocHeight,myDocWidth: INTEGER;
HCRect,myHCRect: Rect;
dummyGrafPtr: GrafPtr;
HCBits: BitMap;
BEGIN
MoveHHi(Handle(theOffScrHandle));
HLock(Handle(theOffScrHandle));
WITH theOffScrHandle^^ DO
BEGIN
myDocWidth := docWidth;
myDocHeight := docHeight;
END;
myBits.rowBytes := (((myDocWidth - 1) DIV 16) + 1) * 2;
myBits.baseAddr := NewPtr(myBits.rowBytes * myDocHeight);
IF (myBits.baseAddr = NIL) THEN
Fail('Could not allocate bitmap.');
HCRect := HCPort^.portRect;
HCBits := HCPort^.portBits;
SetRect(myBits.bounds,0,
0,
528,
358);
dummyGrafPtr := GrafPtr(NewPtr(sizeOf(GrafPort)));
IF (dummyGrafPtr = NIL) THEN
BEGIN
DisposPtr(myBits.baseAddr);
Fail('Could not allocate offscreen grafPort.');
END;
theOffScrHandle^^.gPort := dummyGrafPtr;
OpenPort(theOffScrHandle^^.gPort);
SetOrigin(0,0);
SetPortBits(myBits);
MovePortTo(0,0);
PortSize(myDocWidth,myDocHeight);
RectRgn(theOffScrHandle^^.gPort^.visRgn,theOffScrHandle^^.gPort^.portRect);
RectRgn(theOffScrHandle^^.gPort^.clipRgn,theOffScrHandle^^.gPort^.portRect);
EraseRect(theOffScrHandle^^.gPort^.portRect);
SetRect(myHCRect,0,
0,
512,
342);
CopyBits(HCBits,theOffScrHandle^^.gPort^.portBits,HCRect,myHCRect,srcCopy,NIL);
HUnlock(Handle(theOffScrHandle));
END; {GetHCBitMap}
PROCEDURE AdjustCursor;
{AdjustCursor changes cursorRgn to the region that contains
the cursor. As soon as the cursor moves out of cursorRgn, we
get an event and can change the cursor and cursorRgn again.
cursorRgn is either the content region of our window or
the region containing everything BUT the content region of our
window.}
VAR
mousePt: Point;
myWinContRect: Rect;
myWinContRgn: RgnHandle;
deskRgn: RgnHandle;
handHdl: CursHandle;
BEGIN
SetPort(myWindow);
GetMouse(mousePt);
LocalToGlobal(mousePt);
myWinContRgn := NewRgn;
{Calculate the "work region" of our window, which is its
content region minus the scroll bars and grow icon. This
is the region within which we want the cursor to change
to a cross, and outside of which we want it to be an arrow.}
WITH WindowPeek(myWindow)^.contRgn^^.rgnBBox DO
SetRect(myWinContRect,left, top, right - 15, bottom - 15);
RectRgn(myWinContRgn,myWinContRect);
IF PtInRect(mousePt,myWinContRect) THEN
BEGIN
{The cursor is in the work region of our window}
handHdl := GetCursor(browseTool);
IF (handHdl <> NIL) THEN
SetCursor(handHdl^^)
ELSE
InitCursor;
{Set the cursor region equal to our window's work region.}
SetEmptyRgn(cursorRgn);
CopyRgn(myWinContRgn,cursorRgn);
END
ELSE
BEGIN
{The cursor is outside our window.}
InitCursor;
{Get the current desktop region}
deskRgn := GetGrayRgn;
{Set cursorRgn to the desktop region's bounding box. It is
important to add the menu bar area to cursorRgn too.}
SetRectRgn(cursorRgn, deskRgn^^.rgnBBox.left,
deskRgn^^.rgnBBox.top,
deskRgn^^.rgnBBox.right,
deskRgn^^.rgnBBox.bottom);
{Punch out our window's content region from the big region}
DiffRgn(cursorRgn,myWinContRgn,cursorRgn);
END;
DisposeRgn(myWinContRgn);
END; {AdjustCursor}
BEGIN {Main Program}
{Check the HyperCard version. Must be 1.2 or greater.}
IF GetHCVersion < '1.2' THEN
Fail('Sorry, must have HyperCard 1.2 or greater.');
{Save thy grafPort upon entering!}
GetPort(HCPort);
{Check and reset our environment.}
CheckParamCount;
FlushEvents(everyEvent,0);
InitCursor;
{ Find out what kind of machine we're running on }
envError := SysEnvirons(1,theEnv);
IF (envError <> noErr) THEN
Fail('SysEnvirons call failed.');
{ Convert HyperTalk input parameters for use here }
ZeroToPas(paramPtr^.params[1]^,wTitle);
ZeroToPas(paramPtr^.params[2]^,wT);
ZeroToPas(paramPtr^.params[3]^,wL);
ZeroToPas(paramPtr^.params[4]^,wB);
ZeroToPas(paramPtr^.params[5]^,wR);
wTop := INTEGER(StrToNum(wT));
wLeft := INTEGER(StrToNum(wL));
wBottom := INTEGER(StrToNum(wB));
wRight := INTEGER(StrToNum(wR));
{If window size parameters are too small or illegal, set
the window to a predefined minimum size.}
IF ((wRight - wLeft) < smallestWidth) THEN
wRight := wLeft + smallestWidth;
IF ((wBottom - wTop) < smallestHeight) THEN
wBottom := wTop + smallestHeight;
{Make sure the user is not trying to draw the window off
the screen or under the menubar.}
SetRect(wRect,wLeft,wTop,wRight,wBottom);
IF NOT OnAScreen(wRect) THEN
Fail('You are trying to draw your window off the screen!');
{Get the bounds of the desktop.}
screenRect := GetGrayRgn^^.rgnBBox;
{If we have a small screen, make a note of it so we can hide the
card window during context switches under MultiFinder.}
ZeroToPas(EvalExpr('item 3 of the screenRect')^,widthStr);
screenWidth := INTEGER(StrToNum(widthStr));
ZeroToPas(EvalExpr('item 4 of the screenRect')^,heightStr);
screenHeight := INTEGER(StrToNum(heightStr));
IF (screenWidth = 512) AND (screenHeight = 342) THEN
smallScreen := TRUE
ELSE
smallScreen := FALSE;
HideWindoids;
IF MenuBarHeight > 0 THEN
menuWasHidden := FALSE
ELSE
menuWasHidden := TRUE;
theOffScrHandle := OffScrHandle(NewHandle(SizeOf(OffScrRecord)));
IF MemError <> noErr THEN
Fail('Out of memory. Buy more.');
myDocWidth := HCWidth + padding;
myDocHeight := HCHeight + padding;
MoveHHi(Handle(theOffScrHandle));
HLock(Handle(theOffScrHandle));
WITH theOffScrHandle^^ DO
BEGIN
docWidth := myDocWidth;
docHeight := myDocHeight;
END;
HUnlock(Handle(theOffScrHandle));
GetHCBitMap;
myWindow := NewWindow(@wRecord,wRect,wTitle,TRUE,zoomDocProc,
WindowPtr(-1),TRUE,1);
IF (myWindow = NIL) THEN
BEGIN
DisposPtr(myBits.baseAddr);
ClosePort(myOffScr.gPort);
DisposPtr(Ptr(myOffScr.gPort));
ShowWindoids;
Fail('Not enough memory to draw window.');
END
ELSE
BEGIN
SetWRefCon(myWindow,LONGINT(theOffScrHandle));
InitBlit(myWindow);
DrawGrowIcon(myWindow);
theScrollHandle := ScrollHandle(NewHandle(SizeOf(ScrollRecord)));
IF MemError <> noErr THEN
Fail('Out of memory. Buy more.');
theScrollHandle^^.heldDown := 0;
theScrollHandle^^.goFast := FALSE;
{Draw horizontal and vertical scroll bars in our
window.}
hScroll := CreateHScrollBar(myWindow,0,0,myDocWidth,LONGINT(theScrollHandle));
vScroll := CreateVScrollBar(myWindow,0,0,myDocHeight,LONGINT(theScrollHandle));
HiliteScrollBars(myWindow);
DrawContents(myWindow);
SetRect(dragRect,screenRect.left + 4,
screenRect.top,
screenRect.right - 4,
screenRect.bottom - 4);
largestHeight := screenRect.bottom - screenRect.top;
largestWidth := screenRect.right - screenRect.left;
SetRect(winSizeLimits,smallestWidth,
smallestHeight,
largestWidth,
largestHeight);
HCRefresh := 'Go to this card';
cursorRgn := NewRgn;
inBackGround := FALSE;
DoneFlag := FALSE;
REPEAT
{Call WaitNextEvent, if available. Otherwise call
GetNextEvent.}
IF hasWaitNextEvent THEN
HaveEvent := WaitNextEvent(everyEvent,myEvent,15,cursorRgn)
ELSE
BEGIN
HaveEvent := GetNextEvent(everyEvent,myEvent);
AdjustCursor;
END;
IF HaveEvent THEN
BEGIN
IF (myEvent.what = app4Evt) THEN
{Pre-process app4Evt's fed to us by MultiFinder.}
CASE BSR(myEvent.message,24) OF
MouseMovedEvt:
AdjustCursor;
SuspendResumeEvt:
BEGIN
myEvent.what := activateEvt;
{ Resume event }
IF (BAND(myEvent.message,SuspendEventMask) <> 0) THEN
inBackground := FALSE
ELSE
{ Suspend event }
inBackground := TRUE;
myEvent.message := LONGINT(myWindow);
END; {SuspendResumeEvt}
END; {CASE BSR}
END; {IF HaveEvent}
CASE myEvent.what OF
mouseDown:
BEGIN
partCode := FindWindow(myEvent.where,whichWindow);
IF (whichWindow = myWindow) THEN
BEGIN
{Deal with mouse hits to our window.}
CASE partCode OF
inDrag:
BEGIN
SelectWindow(whichWindow); {DragWindow bug}
DragWindow(whichWindow,myEvent.where,dragRect);
SendCardMessage(HCrefresh);
AdjustCursor;
END;
inGrow:
BEGIN
IF StillDown THEN {GrowWindow bug}
BEGIN
oldSize := whichWindow^.portRect;
newSize := GrowWindow(whichWindow,myEvent.where,winSizeLimits);
IF (newSize <> 0) THEN
BEGIN
InvalScroll(whichWindow);
SizeWindow(whichWindow,LOWORD(newSize),HIWORD(newSize),FALSE);
InvalContents(whichWindow,oldSize);
DrawGrowIcon(whichWindow);
MoveScrollBars(whichWindow);
END; {IF newSize}
END; {IF StillDown}
END; {inGrow}
inZoomIn,inZoomOut:
BEGIN
IF (TrackBox(whichWindow,myEvent.where,partCode)) THEN
BEGIN
InvalScroll(whichWindow);
ZoomIt(whichWindow,partCode,myEvent.where);
InvalContents(whichWindow,oldSize);
DrawGrowIcon(whichWindow);
MoveScrollBars(whichWindow);
END;
END;
inContent:
BEGIN
SetPort(whichWindow);
eventPoint := myEvent.where;
GlobalToLocal(eventPoint);
controlCode := FindControl(eventPoint,whichWindow,whichControl);
ClipRect(whichWindow^.portRect);
IF (controlCode = inThumb) THEN
ScrollWithThumb(whichControl,eventPoint)
ELSE
BEGIN
IF (controlCode <> 0) THEN
BEGIN
WITH ScrollHandle(whichControl^^.contrlRfCon)^^ DO
BEGIN
heldDown := 0;
goFast := FALSE;
END;
dummy := TrackControl(whichControl,eventPoint,@MyScroll);
END; {IF controlCode}
END; {IF controlCode}
END; {inContent}
inGoAway:
BEGIN
IF(TrackGoAway(whichWindow,myEvent.where)) THEN
DoneFlag := TRUE;
END;
END; {CASE partCode}
END
ELSE
BEGIN
IF MenuBarHeight > 0 THEN
BEGIN
FlashMenuBar(0);
Delay(LONGINT(6),dontCare);
FlashMenuBar(0);
END; {IF MenuBarHeight}
END; {IF FindWindow...ELSE}
END; {mouseDown}
activateEvt:
BEGIN
IF(WindowPtr(myEvent.message) = myWindow) THEN
BEGIN
SetPort(myWindow);
ClipRect(myWindow^.portRect);
DrawGrowIcon(myWindow);
IF inBackground THEN
BEGIN
{We've been sent behind another application
under MultiFinder, so deactivate the scroll
bars and show the menubar if it was hidden.}
Deactivate(myWindow);
IF smallScreen THEN
ShowHide(WindowPtr(HCPort),FALSE);
IF MenuBarHeight = 0 THEN
BEGIN
SendHCMessage('show menubar');
menuWasHidden := TRUE;
END
ELSE
menuWasHidden := FALSE;
END
ELSE
BEGIN
{We've been brought to the front under Multi-
Finder, so reactivate the scroll bars and
hide the menubar if it was hidden before.}
ShowHide(WindowPtr(HCPort),TRUE);
IF menuWasHidden THEN
SendHCMessage('hide menubar');
DrawControls(myWindow);
HiliteScrollBars(myWindow);
FlushEvents(everyEvent,0);
END; {IF inBackground}
END; {IF WindowPtr}
END; {activateEvt}
updateEvt:
BEGIN
{Handle updates to our window.}
IF(WindowPtr(myEvent.message) = myWindow) THEN
BEGIN
{Always do this stuff}
SetPort(myWindow);
BeginUpdate(myWindow);
ClipRect(myWindow^.portRect);
DrawGrowIcon(myWindow);
{Always do this stuff under single Finder but
only if in foreground under MultiFinder}
IF NOT inBackground THEN
BEGIN
HiliteScrollBars(myWindow);
DrawControls(myWindow);
AdjustCursor;
END;
{Always do this stuff}
DrawContents(myWindow);
EndUpdate(myWindow);
END {IF myEvent.message}
{Handle updates to HyperCard's card window.}
ELSE IF (WindowPtr(myEvent.message) = WindowPtr(HCPort)) THEN
BEGIN
SendHCMessage(HCRefresh);
{Must zero out card window's update region
ourselves because the SendHCMessage call
doesn't do it, and we'll wind up in an
infinite loop if we don't.}
BeginUpdate(WindowPtr(HCPort));
EndUpdate(WindowPtr(HCPort));
END; {IF... ELSE}
END; {updateEvt}
keyDown:
BEGIN
IF(BitAnd(myEvent.modifiers,cmdKey) <> 0) THEN
BEGIN
charCode := BitAnd(myEvent.message,charCodeMask);
{Pressing command-spacebar toggles the menubar.}
IF(CHR(charCode) = ' ') THEN
ToggleMenuBar
{Pressing command-W closes the window and exits
the XCMD.}
ELSE IF(CHR(charCode) = 'w') THEN
DoneFlag := True;
END;
END;
END; {CASE myEvent.what}
UNTIL (DoneFlag = True);
{Clean up and get outta here!}
DisposeRgn(cursorRgn);
DisposPtr(myBits.baseAddr);
ClosePort(theOffScrHandle^^.gPort);
DisposPtr(Ptr(theOffScrHandle^^.gPort));
DisposHandle(Handle(theOffScrHandle));
DisposHandle(Handle(theScrollHandle));
CloseWindow(myWindow);
SendCardMessage(HCrefresh);
ShowWindoids;
InitCursor;
FlushEvents(everyEvent,0);
{Restore thy grafPort}
SetPort(HCPort);
END; {IF myWindow...ELSE}
END; {Main}
END. {Window}